xtask\tasks\guest_test\uefi/
mod.rs

1// Copyright (c) Microsoft Corporation.
2// Licensed under the MIT License.
3
4use crate::Xtask;
5use clap::Parser;
6use std::path::Path;
7use std::path::PathBuf;
8use xshell::cmd;
9
10mod gpt_efi_disk;
11
12/// Build a UEFI test image.
13#[derive(Parser)]
14pub struct Uefi {
15    // Output disk image. If left blank, outputs disk at `<bootx64/bootaa64>.img`
16    // if only one EFI boot file is provided.
17    //
18    // Extension determines disk type.
19    //
20    // Only `.img` disk image files currently supported.
21    #[clap(long)]
22    output: Option<PathBuf>,
23
24    /// File to set as `bootx64.efi`. Builds `guest_test_uefi` for x64 if no file is provided (default).
25    #[clap(long)]
26    #[expect(clippy::option_option)]
27    bootx64: Option<Option<PathBuf>>,
28
29    /// File to set as `bootaa64.efi`. Builds `guest_test_uefi` for ARM64 if no file is provided.
30    #[clap(long)]
31    #[expect(clippy::option_option)]
32    bootaa64: Option<Option<PathBuf>>,
33}
34
35impl Xtask for Uefi {
36    fn run(self, _ctx: crate::XtaskCtx) -> anyhow::Result<()> {
37        let mut files = Vec::new();
38
39        // Default case: build x64
40        let bootx64 = if self.bootx64.is_none() && self.bootaa64.is_none() {
41            Some(None)
42        } else {
43            self.bootx64
44        };
45
46        if let Some(bootx64) = bootx64.as_ref() {
47            if let Some(bootx64) = bootx64 {
48                files.push((Path::new("efi/boot/bootx64.efi"), bootx64.as_path()));
49            } else {
50                let sh = xshell::Shell::new()?;
51                cmd!(
52                    sh,
53                    "cargo build -p guest_test_uefi --target x86_64-unknown-uefi"
54                )
55                .run()?;
56
57                files.push((
58                    Path::new("efi/boot/bootx64.efi"),
59                    Path::new("./target/x86_64-unknown-uefi/debug/guest_test_uefi.efi"),
60                ));
61            }
62        }
63
64        if let Some(bootaa64) = self.bootaa64.as_ref() {
65            if let Some(bootaa64) = bootaa64 {
66                files.push((Path::new("efi/boot/bootaa64.efi"), bootaa64.as_path()))
67            } else {
68                let sh = xshell::Shell::new()?;
69                cmd!(
70                    sh,
71                    "cargo build -p guest_test_uefi --target aarch64-unknown-uefi"
72                )
73                .run()?;
74
75                files.push((
76                    Path::new("efi/boot/bootaa64.efi"),
77                    Path::new("./target/aarch64-unknown-uefi/debug/guest_test_uefi.efi"),
78                ));
79            }
80        }
81
82        let out_img = match self.output {
83            Some(path) => path,
84            None => {
85                if files.len() != 1 {
86                    anyhow::bail!(
87                        "Multiple EFI files specified. Please provide an explicit output path."
88                    )
89                }
90                files[0].1.with_extension("img")
91            }
92        };
93
94        gpt_efi_disk::create_gpt_efi_disk(&out_img, &files)?;
95
96        Ok(())
97    }
98}